package com.duoqin.syncassistant.ui;

import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.widget.ListPopupWindow;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;

import com.duoqin.account.DuoqinAccount;
import com.duoqin.common.data.DefaultResponse;
import com.duoqin.syncassistant.R;
import com.duoqin.syncassistant.sms.SmsData;
import com.duoqin.syncassistant.sms.SmsInfoUtil;
import com.duoqin.syncassistant.SyncAssistantApplication;
import com.duoqin.syncassistant.data.BackupFileDownloadResponse;
import com.duoqin.syncassistant.data.BackupFileInfo;
import com.duoqin.syncassistant.viewmodel.BaseViewModel;
import com.duoqin.syncassistant.viewmodel.SMSSyncViewModel;
import com.google.gson.Gson;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;

public class SMSSyncActivity extends BaseSyncActivity {

    private SMSSyncViewModel mViewModel;
    private ArrayList<SmsData> mSmsList;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupTitle(getString(R.string.sms_sync));
        mServerRecordsCountView.setText(
                String.valueOf(SyncAssistantApplication.getsInstance().mSMSInfo.getCount()));

        mBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (SmsInfoUtil.INTENT_ACTION_SMS.equals(action)) {
                    String smsPath = intent.getStringExtra(SmsInfoUtil.INTENT_EXTRA_SMS_PATH);
                    Log.d(TAG, "smsPath = " + smsPath);
                    if (smsPath != null) {
                        mViewModel.backupSMS(DuoqinAccount.getAccountToken(context),
                                mPhoneRecordsCount, smsPath);
                    } else {
                        Toast.makeText(getApplicationContext(), R.string.sms_generic_failure,
                                Toast.LENGTH_SHORT).show();
                        showProgress(false);
                    }
                }
            }
        };

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(SmsInfoUtil.INTENT_ACTION_SMS);
        LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, intentFilter);
    }

    @Override
    protected void queryLocalRecords() {
        mSmsList = SmsInfoUtil.getPhoneSms(getApplicationContext());
        if (mSmsList != null) {
            mPhoneRecordsCount = mSmsList.size();
        } else {
            mPhoneRecordsCount = 0;
        }
        mPhoneRecordsCountView.setText(String.valueOf(mPhoneRecordsCount));
        Log.d(TAG, "SMS Count = " + mPhoneRecordsCount);
    }

    @Override
    protected void setupModelObserver() {
        mViewModel = ViewModelProviders.of(this).get(SMSSyncViewModel.class);

        final Observer<DefaultResponse> smsBackupObserver = new Observer<DefaultResponse>() {
            @Override
            public void onChanged(@Nullable DefaultResponse response) {
                Log.i(TAG, "onChanged smsBackupResponse = " + response);
                if (response != null) {
                    Log.d(TAG, "onChanged code = " + response.getCode()
                            + "; msg = " + response.getMsg());
                    Log.d(TAG, "onChanged data = " + response.getData());
                    if (BaseViewModel.SERVER_RESULT_SUCCESS == response.getCode()) {
                        Toast.makeText(getApplicationContext(), R.string.backup_success,
                                Toast.LENGTH_SHORT).show();
                        setResult(RESULT_OK);
                        finish();
                        return;
                    }
                    Toast.makeText(getApplicationContext(), R.string.backup_fail,
                            Toast.LENGTH_SHORT).show();
                }
                showProgress(false);
            }
        };
        mViewModel.smsBackupResponse().observe(this, smsBackupObserver);

        final Observer<BackupFileDownloadResponse> smsDownloadObserver =
                new Observer<BackupFileDownloadResponse>() {
            @Override
            public void onChanged(@Nullable BackupFileDownloadResponse response) {
                Log.i(TAG, "onChanged BackupFileDownloadResponse = " + response);
                if (response != null) {
                    if (BaseViewModel.SERVER_RESULT_SUCCESS == response.getCode()) {
                        String smsPath = response.getPath();
                        Log.i(TAG, "onChanged smsPath = " + smsPath);
                        Intent intent = new Intent("com.duoqin.importSMS");
                        intent.addCategory(Intent.CATEGORY_DEFAULT);
                        final Uri contentUri = FileProvider.getUriForFile(getApplicationContext(),
                                getString(R.string.file_provider_authority),
                                new File(smsPath));
                        intent.setDataAndType(contentUri, "text/plain");
                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                        intent.setPackage("com.android.messaging");
                        startService(intent);
                        Toast.makeText(getApplicationContext(), R.string.restore_sms_in_background,
                                Toast.LENGTH_SHORT).show();
                        finish();
                    } else {
                        Toast.makeText(getApplicationContext(), R.string.restore_fail,
                                Toast.LENGTH_SHORT).show();
                    }
                }
            }
        };
        mViewModel.downloadSMSResponse().observe(this, smsDownloadObserver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
    }

    @Override
    protected void attemptRestore() {
        if (SyncAssistantApplication.getsInstance().mAllSMSFiles.size() > 1) {
            LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
            SMSAdapter smsAdapter = new SMSAdapter(this, inflater);
            if (mListPopupWindow == null) {
                mListPopupWindow = new ListPopupWindow(this);
                mListPopupWindow.setAnchorView(findViewById(R.id.info_panel));
                mListPopupWindow.setAdapter(smsAdapter);
                mListPopupWindow.setModal(true);
                mListPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        position = position - mListPopupWindow.getListView().getHeaderViewsCount();
                        if (position < SyncAssistantApplication.getsInstance().mAllSMSFiles.size()) {
                            BackupFileInfo smsInfo = SyncAssistantApplication.getsInstance().mAllSMSFiles
                                    .get(position);
                            if (!TextUtils.isEmpty(smsInfo.getPath())) {
                                showProgress(true);
                                mViewModel.downloadSMS(smsInfo.getPath(), smsInfo.getHash());
                            }
                        }
                        mListPopupWindow.dismiss();
                    }
                });
                mListPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
                    @Override
                    public void onDismiss() {
                        mDimBgView.setVisibility(View.GONE);
                    }
                });
                mListPopupWindow.show();
            }
            if (mListPopupWindow.getListView() == null) {
                mListPopupWindow.show();
            }
            if (0 == mListPopupWindow.getListView().getHeaderViewsCount()) {
                View titleView = inflater.inflate(R.layout.list_records_title,
                        mListPopupWindow.getListView(), false);
                mListPopupWindow.getListView().addHeaderView(titleView, null, false);
            }
            if (0 == mListPopupWindow.getListView().getFooterViewsCount()) {
                View footerView = inflater.inflate(R.layout.list_records_footer,
                        mListPopupWindow.getListView(), false);
                mListPopupWindow.getListView().addFooterView(footerView, null, false);
            }
            mListPopupWindow.show();
            mDimBgView.setVisibility(View.VISIBLE);
        } else {
            if (!TextUtils.isEmpty(SyncAssistantApplication.getsInstance().mSMSInfo.getPath())) {
                showProgress(true);
                mViewModel.downloadSMS(SyncAssistantApplication.getsInstance().mSMSInfo.getPath(),
                        SyncAssistantApplication.getsInstance().mSMSInfo.getHash());
            } else {
                Toast.makeText(getApplicationContext(), R.string.restore_sms_not_found,
                        Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    protected void attemptBackup() {
        showProgress(true);
        if (mPhoneRecordsCount > 0) {
            new Runnable() {
                @Override
                public void run() {
                    if (mSmsList != null && mSmsList.size() > 0) {
                        File file = null;
                        try {
                            Gson gson = new Gson();
                            String smsString = gson.toJson(mSmsList);
                            file = new File(getApplication().getCacheDir(),
                                    SmsInfoUtil.SMS_FILE_NAME);
                            if (file.exists()) {
                                file.delete();
                            }
                            FileOutputStream fos = new FileOutputStream(file);
                            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos));
                            writer.write(smsString);
                            writer.close();
                            fos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                            Intent exportIntent = new Intent(SmsInfoUtil.INTENT_ACTION_SMS);
                            if (file != null) {
                                exportIntent.putExtra(SmsInfoUtil.INTENT_EXTRA_SMS_PATH,
                                        file.getAbsolutePath());
                            }
                            LocalBroadcastManager.getInstance(SMSSyncActivity.this)
                                    .sendBroadcast(exportIntent);
                            Log.i(TAG, "finished exporting sms " + mSmsList.size());
                        }
                    }
                }
            }.run();
        } else {
            Toast.makeText(getApplicationContext(), R.string.fail_reason_no_exportable_sms,
                    Toast.LENGTH_SHORT).show();
            showProgress(false);
        }
    }

    private final static class SMSAdapter extends BaseAdapter {
        private final Context mContext;
        private final LayoutInflater mInflater;

        public SMSAdapter(Context context, LayoutInflater inflater) {
            mContext = context;
            mInflater = inflater;
        }

        @Override
        public int getCount() {
            return SyncAssistantApplication.getsInstance().mAllSMSFiles.size();
        }

        @Override
        public Object getItem(int position) {
            return SyncAssistantApplication.getsInstance().mAllSMSFiles.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final View resultView =
                    (convertView != null) ? convertView
                            : mInflater.inflate(R.layout.list_item_record, parent, false);
            final TextView createdTimeTV = resultView.findViewById(R.id.created_time);
            final TextView countTV = resultView.findViewById(R.id.records_count);

            BackupFileInfo smsInfo = SyncAssistantApplication.getsInstance().mAllSMSFiles.get(position);
            createdTimeTV.setText(DateUtils.formatDateTime(mContext, smsInfo.getCreateAt(),
                    DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE
                            | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_NUMERIC_DATE));
            countTV.setText(mContext.getString(R.string.items_count_of_record,
                    smsInfo.getCount()));
            return resultView;
        }
    }
}
